﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Mediator
{
    class Program
    {
        static void Main(string[] args)
        {
            //ConcreteMediator cm = new ConcreteMediator();
            //ConcreteColleague1 c1 = new ConcreteColleague1(cm);
            //ConcreteColleague2 c2 = new ConcreteColleague2(cm);

            //cm.ConcreteColleague1 = c1;
            //cm.ConcreteColleague2 = c2;

            //c1.Send("how are you");
            //c2.Send("fine thank you");


            // Create chatroom
            Chatroom chatroom = new Chatroom();

            // Create participants and register them
            Participant George = new Beatle("George");
            Participant Paul = new Beatle("Paul");
            Participant Ringo = new Beatle("Ringo");
            Participant John = new Beatle("John");
            Participant Yoko = new NonBeatle("Yoko");

            chatroom.Register(George);
            chatroom.Register(Paul);
            chatroom.Register(Ringo);
            chatroom.Register(John);
            chatroom.Register(Yoko);

            // Chatting participants
            Yoko.Send("John", "Hi John!");
            Paul.Send("Ringo", "All you need is love");
            Ringo.Send("George", "My sweet Lord");
            Paul.Send("John", "Can't buy me love");
            John.Send("Yoko", "My sweet love");

            Console.Read();
        }
    }

    //abstract class Mediator
    //{
    //    public abstract void Send(string message, Colleague colleague);
    //}

    //class ConcreteMediator : Mediator
    //{
    //    private ConcreteColleague1 _concreteColleague1;
    //    private ConcreteColleague2 _concreteColleague2;

    //    public ConcreteColleague1 ConcreteColleague1
    //    { set { _concreteColleague1 = value; } }
    //    public ConcreteColleague2 ConcreteColleague2
    //    { set { _concreteColleague2 = value; } }

    //    public override void Send(string message, Colleague colleague)
    //    {
    //        if (colleague == _concreteColleague1)
    //        {
    //            _concreteColleague2.Notify(message);
    //        }
    //        else
    //        {
    //            _concreteColleague1.Notify(message);
    //        }
    //    }
    //}

    //abstract class Colleague
    //{
    //    protected Mediator mediator;

    //    public Colleague(Mediator mediator)
    //    {
    //        this.mediator = mediator;
    //    }
    //}

    //class ConcreteColleague1 : Colleague
    //{
    //    public ConcreteColleague1(Mediator mediator):base(mediator)
    //    { 
    //    }

    //    public void Send(string message)
    //    {
    //        mediator.Send(message, this);
    //    }

    //    public void Notify(string message)
    //    {
    //        Console.WriteLine("{0} get message: {1}",this.GetType().Name, message);
    //    }
    //}

    //class ConcreteColleague2 : Colleague
    //{
    //    public ConcreteColleague2(Mediator mediator)
    //        : base(mediator)
    //    {
    //    }

    //    public void Send(string message)
    //    {
    //        mediator.Send(message, this);
    //    }

    //    public void Notify(string message)
    //    {
    //        Console.WriteLine("{0} get message: {1}",this.GetType().Name, message);
    //    }
    //}

    abstract class AbstractChatroom
    {
        public abstract void Register(Participant participant);
        public abstract void Send(string from, string to, string message);
    }

    class Chatroom : AbstractChatroom
    {
        private Dictionary<string, Participant> _participants
            = new Dictionary<string, Participant>();

        public override void Register(Participant participant)
        {
            if (!_participants.ContainsValue(participant))
            {
                _participants[participant.Name] = participant;
            }
            participant.Chatroom = this;
        }

        public override void Send(string from, string to, string message)
        {
            Participant participant = _participants[to];

            if (participant != null)
            {
                participant.Recieve(from, message);
            }
        }
    }

    class Participant
    {
        public string Name { get; set; }
        public AbstractChatroom Chatroom { get; set; }

        public Participant(string name)
        {
            this.Name = name;
        }

        public void Send(string to, string message)
        {
            Chatroom.Send(this.Name, to, message);
        }

        public virtual void Recieve(string from, string message)
        {
            Console.WriteLine("{0} to {1}: '{2}'", from, Name, message);
        }
    }

    class Beatle : Participant
    {
        public Beatle(string name)
            : base(name)
        {}

        public override void Recieve(string from, string message)
        {
            Console.WriteLine("To a Beatle: ");
            base.Recieve(from, message);
        }
    }

    class NonBeatle : Participant
    {
        public NonBeatle(string name) : base(name) { }

        public override void Recieve(string from, string message)
        {
            Console.WriteLine("To a non-Beatle: ");
            base.Recieve(from, message);
        }
    }
}
